home *** CD-ROM | disk | FTP | other *** search
- PostScript shared library interface (post.library, with HWGPOST >= V22.21)
- ==========================================================================
-
- HWGPOST, Copyright 1993, 1994 Heinz Wrobel, is mostly calling compatible to
- Post V1.7, Copyright Adrian Aylward 1991, 1992. But it is a very different
- beast inside.
-
- This document is derived from Adrian Aylward's post.library documentation.
-
-
-
- Introduction
- ============
-
- The file "post.library" is an AmigaOS Exec shared library containing a
- mostly Level II compliant PostScript interpreter. It is designed to be
- shareable between different processes, supporting arbitrarily many
- PostScript activations - at least until you run out of memory.
-
- This file should be read in conjunction with the header file "postlib.h".
-
- The standard user interface source files are distributed with old Post 1.7.
- Read them as examples for now. If there is different information in this
- document or the current headerfile postlib.h or init.ps, the
- current information holds.
-
-
- Activation Records
- ==================
-
- Simultaneous multiple activations of PostScript are allowed. Before using
- post.library you must first open it by a call to OpenLibrary(). To create
- an activation you then call PScreateact() which returns a pointer to the
- activation record. You can then make calls to the interpreter library,
- passing the activation record pointer as an argument. You can create
- several activations, possibly from different processes and intermingle
- the interpreter calls if you wish. But you CANNOT PASS ACTIVATION RECORDS
- BETWEEN PROCESSES! When you have finished with an activation, call
- PSdeleteact() to delete it and free the memory it used. When you have
- finished with the library call CloseLibrary(); if no other processes have it
- open, then Exec can remove it from memory if the space is needed. (N.B. if
- the space is not needed, the library will remain in memory in case it is
- opened again.)
-
- N.B. the library can only be called from a process, as it calls various
- AmigaDOS functions. IT IS NOT PERMISSIBLE TO PASS ACTIVATION RECORDS
- BETWEEN PROCESSES! NOTE THIS WELL!
-
-
- The Parameter Block
- ===================
-
- The parameter block is the argument to PScreateact(). It is specifies the
- addresses of the bitmap planes, size of the page, and the amount of memory
- to be allocated for the activation etc ... Its format is defined in detail
- in the header file postlib.h.
-
- N.B. all ints are 32 bits, shorts are 16 bits.
-
- The page size is limited to 30000 pixels a side. The densities (pixels per
- inch) may be any strictly positive integer value. The y direction may be
- set to +1 - if the bitmap rows are in PostScript order (bottom row first)
- or -1 - Amiga order (top row first).
-
- page.buf[24] Bitplane pointers, up to 24
- page.len Size in bytes of each plane
- page.depth Number plane pointers to use
- page.flags Special device options
- page.bitspercolor How many plane pointers to be used per gun.
- page.PSextdevice An optional extension to the device information
- page.xbytes Number of bytes in each row
- page.xsize Number of pixels in each row
- page.ysize Number of rows
- page.ybase Base of current band
- page.yheight Total height of full page, for band rendering
- page.xden X density
- page.yden Y density
- page.ydir Y direction
-
- To specify how many bitplanes are used per color, you set "bitspercolor" to
- the appropriate value. If this value is not set, one bitplane per color is
- assumed and only 1, 3, and 4 are permissible as depth in this case.
- Example: RGB 3:3:2 => depth=8, bitspercolor=3.
-
- Note that bitspercolor should not exceed 8.
-
- For special use, the page device description can be enhanced by setting
- page.PSextdevice. The PSextdevice structure contains the following fields.
-
- flags Extension of the main flags field.
-
- maskbuf If set, must be a plane as in page.buf. For any
- rendering you'll get bits set in this mask plane.
- This gives you a mask of the actually used places
- in the buffer. The mask might be useful for
- BltMaskBitMapRastPort() or some such. erasepage
- will clear this mask plane.
-
- Kbuf[8] Eight additional plane pointers to allow for true
- eight bit CMYK rendering. You need to set the depth
- to a value greater 24 for these to be used.
-
- The length of these structures is subject to change. Always set unused fields
- to zero.
-
- As a starting point for memory sizes try the values following. (These are
- defined in the header file.) For normal PostScript programs the defaults
- are perfectly satisfactory. If you specify a value of zero the default
- will be used instead; values less than the minimum will be increased.
-
- memvlen 50000 VM
- memflen 60000 Font cache
- memllen 15000 Path lines
- memhlen 20000 Halftones
- memplen 60000 Pattern cache
-
- The user data pointer is intended to be used to identify multiple
- activations. You can set it to any value you like. The function pointers
- are described below.
-
- userdata User data pointer
- flushfunc Flush page function pointer
- copyfunc Copy page function pointer
-
- The standard input and output streams are the AmigaDOS file handles to be
- used by the interpreter for %stdin, %stdout, %stderr. Also the standard
- output is used for prompts and the error output for error messages. These
- file handles will not be closed by the interpreter even though PostScript
- file objects referring to them may be closed.
-
- infh Standard Input file handle
- outfh Standard Output file handle
- errfh Standard Error file handle
-
- These are for backwards compatibility with the infamous "callextfunc"
- operator. You'll find details below.
-
- funcmax Number of external functions
- functab Pointer to external function table, or zero
-
- Anything else in the block is reserved and must be set to zero.
-
- Notes on the special device flags
- ---------------------------------
-
- In the header file "postlib.h" you will find some flag definitions for the
- main flag field of the parameter page. They need more explanation.
-
- HWGPOST_DEVx_NOSHADE
-
- Halftoning is in effect suppressed. No halftone screens will be
- used. Any color intensity that would cause shading will be rendered
- as the next lower color value truly representable within the
- bitplanes would. Shading is simply "cut out".
-
- HWGPOST_DEVx_CMYK
-
- Old post.library supported the CMYK color space and operators. When
- converting any colors to values passed to the transfer functions,
- it creates RGBW values, though, instead of CMYK. With this flag
- set, the colorspace mapping algorithm will stay with CMYK and CMYK
- will be passed to the transfer functions if applicable.
-
- HWGPOST_DEVx_INVERTOUTPUT
-
- The output of the transfer functions represent the value that
- should be rendered into the bitplanes. With this flag set,
- these values in the range [0.0;1.0] will effectively reversed with
- a simple "shade = 1.0 - shade" before the rendering is set up. This
- is the easiest way to create "negative" output and might come in
- handy for multiple bitplane color handling, where black should be
- "all bits 0" instead of "all bits 1" in the planes.
-
-
- Function Pointers
- =================
-
- There are two function pointers within the parameter block, which are used
- when the interpreter needs to call routines supplied by its client. If the
- pointers are zero, the calls are skipped.
-
- To help identify calls from multiple activations, the activation record
- address is also passed in A0 and the userdata pointer in A1.
-
- flushfunc(D0: int y1, D1: int y2)
-
- Flush the bitmap to the screen. The interpreter calls this function after
- a painting operation has updated the bitmap. Then if the output is being
- viewed interactively the client can update the screen or window. The
- arguments are the range of bitmap rows (y1 ... y2-1) that may have been
- updated.
-
- copyfunc(D0: int num)
-
- Copy the page to the output device. The argument is the value of
- "#copies", which should be taken into account if the output is to a
- printer, but is not meaningful for screen output.
-
-
- Calling External Functions
- ==========================
-
- The original "callextfunc" operator of post.library <= V1.7 is no longer
- supported even though it is still available in disguise as "@callextfunc".
- Use of this operator is strongly discouraged as it might lure you into
- making assumptions about internal HWGPOST data representations.
-
- A more general way to call external functions has been devised via the new
- "@calluserhook" operator. This operator collects the arguments, passes them
- to a "Hook" as defined by the utility.library, records any changes and
- returns the result. This is the calling sequence:
-
- mark <args..> <userhookadr> <msgadr> @calluserhook
-
- On return the operand stack will look like this:
-
- mark <args..> <resint>
-
- A number from zero to eight arguments is supported. Only certain PostScript
- objects may be passed as arguments: integers, reals, and booleans are
- passed as the 32 bit bitpatterns corresponding to their values; strings are
- passed as the 32 bit address of their contents with the length as the
- following 32 bit integer. (N.B. PostScript strings are terminated by
- length; there is no terminating null unless the program puts one there. The
- user function may not go beyond the string length!)
-
- <hookadr> and <msgadr> are integers that are used as 32 bit memory address.
- If no <msgadr> is needed, just use 0. These addresses should be passed to
- the interpreter via the PSintstring() function in full PostScript notation
- like "/hookadr 16#780ab44 def" to be used by special PostScript code. It is
- advisable to put them into special, private dictionaries.
-
- The argument values passed are put into an array of 32 bit values which is
- passed as "objectptr" to the Hook. The return value will be put on the
- operand stack as <resint> and any changes to numeric values in the 32 bit
- array will be put back into the args on the operand stack. The Hook may
- change string contents within the address and length passed to it.
-
- As an example assume this calling sequence:
-
- mark 1 string1 2.5 4 string2 false hookadr 0 @calluserhook
-
- The 32 bit array passed to the hook as object will have these contents:
-
- array[0]: 32 int 1
- array[1]: string1: address
- array[2]: string1: length
- array[3]: IEEE float 2.5
- array[4]: 32 int 4
- array[5]: string2: address
- array[6]: string2: length
- array[7]: 0
-
- If the hook function changes array[0] to 3, array[7] to 1, and returns -1,
- the resulting operand stack will contain these values:
-
- mark 3 string1 2.5 4 string2 true -1
-
- Changing a string address or length should not be tried. If results are not
- needed, a cleartomark will get rid of them easily.
-
- There should not be any assumptions made about internal representation of
- objects. For booleans, only 0 and 1 should be used.
-
- N.B. PSintstring() is not guaranteed to work recursively. So calling it
- from the hook is not a good idea. The Hook is called on the interpreters
- context. If a local near data section is needed, the Hook function is
- responsible for setting up A4, e.g. from hook->h_Data. Standard rules for
- saving registers apply. Do not assume that A4 contains anything useful!
-
-
- Calling External Functions with @callextfunc
- ============================================
-
- The original "callextfunc" operator of post.library <= V1.7 is no longer
- supported even though it is still available in disguise as "@callextfunc".
- Use of this operator is strongly discouraged as it might lure you into
- making assumptions about internal HWGPOST data representations. It is only
- here for limited backwards compatibility. Do not use it for new SW!
-
- If you supply an external function table your PostScript program can call
- the functions within it by the "@callextfunc" operator. The contents of
- the table are the addresses of the function entry points. The functions
- must have standard (Lattice, non-registerised) C compatible calling
- sequences. They must not assume any useful value in register A4 on entry,
- and must preserve A4 and the other C registers on exit.
-
- Unlike with post.library <= 1.7 there is additional information given,
- though. To help identify calls from multiple activations, the activation
- record address is also passed in A0 and the userdata pointer in A1.
-
- Only certain PostScript objects may be passed as arguments: integers reals
- and booleans are passed as the 32 bit bitpatterns corresponding to their
- values; arrays and strings are passed as the 32 bit address of their
- contents - if the length is required it must be passed separately. (N.B.
- PostScript strings are terminated by length; there is no terminating null
- unless the program puts one there.)
-
- It is theoretically possible to pass arbitrary objects by including them
- within an array, but then you would need to know their PostScript
- representation. As the representation has been changed thoroughly for
- HWGPOST and will continue to change in the future, this "feature" is of no
- use at all!
-
- The "@callextfunc" operator is only inserted into the system dictionary if
- a function table is present. So you will not find it if you attempt to
- execute it from the standard user interface.
-
-
- Library Entry points
- ====================
-
- Prototypes and pragmas for the entry points are defined in the header file.
-
-
- Create a PostScript activation
- ------------------------------
-
- D0:int arec = PScreateact(A1:struct PSparm *parm)
-
- The result is the address of the new activation record. If the activation
- fails an error code is returned instead - zero if the interpreter failed
- to start at all because there was insufficient free memory, or an
- interpreter error code if there was an error during initialisation.
- Otherwise the result is the address of the activation record. The result
- is always returned as an int. If is is greater than errmax then the
- activation was successful, and the value is an address; otherwise the
- activation failed, and the result is zero or an error code.
-
-
- Delete a PostScript activation
- ------------------------------
-
- VOID PSdeleteact(A0:APTR arec)
-
- The activation record is deleted and the associated memory is freed.
-
-
- Interpret a string or file
- --------------------------
-
- D0:int errnum = PSintstring(A0:APTR arec, A1:char *string,
- D0:int length, D1:int flags)
-
-
- Flag bits:
-
- PSFLAGSTRING, PSFLAGGFILE
-
- If PSFLAGSTRING is set, the contents of the string are interpreted
- as PostScript source. If the flag PSFLAGFILE is set, the string is
- a file name, whose contents are interpreted. If neither of these
- flag bits are set the string is ignored, but the other flag bits
- still have their effects; if both are set the result is undefined.
-
-
- PSFLAGINTER
-
- If PSFLAGINTER is set (when interpreting a file), the file is
- considered to be interactive. The banner is printed, and the
- interpreter prompts for each line of input from the file.
-
-
- PSFLAGCLEAR
-
- If PSFLAGCLEAR is set, then after interpretation the operand stack
- is cleared and the dictionary stack is popped until only the system
- and user dictionaries remain. The execution stack is emptied, too.
-
-
- PSFLAGSAVE
-
- If PSFLAGSAVE is set, job server behaviour is set up for the
- current job only. It is functionally equivalent to
- (PSFLAGSTARTJOBSERVER| PSFLAGENDJOBSERVER) but you shouldn't use
- the job server flags instead if you really want PSFLAGSAVE.
-
-
- PSFLAGERASE
-
- If PSFLAGERASE is set, then the page is erased. This happens right
- at the end, after any vm restore, so the page is erased taking into
- account the restored transfer function(s).
-
- PSFLAGSTARTJOBSERVER, PSFLAGENDJOBSERVER
-
- With PSFLAGSTARTJOBSERVER and PSFLAGENDJOBSERVER one can create one
- job server run, spanning multiple invocations of PSintstring(). The
- former forces a successful startjob with a "false" operand before
- running the job, the latter forces a successful startjob with a
- "true" operand after running the job and clears out the execution
- stack and does some other private things. These flags do not nest.
- If you think about using them in a tricky way: Think again and ask
- _first_.
-
- This routine is NOT guaranteed to recurse correctly; strange things or
- crashes may happen if you try to call it from an external function called
- from the same activation.
-
-
- Signal an interrupt
- -------------------
-
- VOID PSsignalint(A0:APTR arec, D0:int flag)
-
- This routine may be called to set an interrupt signal flag to notify the
- interpreter of a special condition. The possible flag values are defined in
- the header file postlib.h. You may or multiple bit flags together. The
- interpreter tests these flags at the head of its main loop, and also within
- certain potentially length operators (=, ==, stack and pstack). If a flag
- is set it the interpreter will take appropriate action immediately and
- automatically clear the corresponding flag bit. You may safely call this
- routine at any time during the life of the activation. It is intended to be
- called from within your task's exception handler, if the CTRL-C break
- signal is set. Unlike with post.library <= V1.7 it is not possible to clear
- a flag once it has been set by calling this function. Only the interpreter
- will clear a flag bit when it is handled.
-
-
- Signal a floating point error
- -----------------------------
-
- VOID PSsignalfpe(A0:APTR arec)
-
- This routine is intended to be called whenever a floating point trap is
- generated by the interpreter. It generates an immediate undefinedresult
- error. You must not call it at any other time; if you do you will crash
- the machine. It is only useful if you are using the version of the library
- compiled for the 68881 FPU or compatible chips. (The software floating
- point routines do not generate traps). Before calling the library you
- should set up a trap handler and set the bits in the fpcr register to
- enable the traps. (If you do not set up the traps, the FPU will substitute
- the special value not-a-number for the result and continue. The
- undefinedresult error will not be triggered, and results of your program
- may be incorrect.) If you application does not use the FPU you can simply
- direct all traps to the library, otherwise it is essential that you
- ensure that you only call this routine if the trap derived from the library
- and not your own code.
-
-
- Error
- -----
-
- VOID PSerror(A0:APTR arec, D0:int errnum)
-
- This routine is intended to be called from within your own flush or copy
- page functions, to signal that an error ocurred. You can also call it from
- an external function. You must not call it at any other time; if you do, you
- will crash the machine. It calls the PostScript error handler and never
- returns. The values for the error number are defined in the header file.
-
-
- Return a text string corresponding to an error name
- ---------------------------------------------------
-
- D0:const char *str = PSerrstr(A0:int arec, D0:int errnum)
-
- Converts a postscript error number to a text string. Returns NULL if the
- number is out of range.
-
-
- Change device page
- ------------------
-
- VOID PSsetdevice(A0:APTR arec, A1:struct PSdevice *page)
-
- Note: While "setpagedevice" is not currently available, the effects caused
- by PSsetdevice() are _very_ likely to change in many ways when the
- time comes. If you feel that you rely on effects other than simply
- replacing the device page buffer and dimensions CONTACT ME NOW.
-
- Changes the device page buffer and dimensions. If the clip path is still
- set to its initial value (the whole page) it is changed to match the new page
- size; otherwise it is unchanged (and may therefore possibly exceed the new
- page size). All the clip paths saved on the graphics stack are similarly
- changed. The CTM at the topmost saved graphics state (the one returned to
- by a "grestoreall" when there are no active VM saves) is reset to match the
- new page size and density. Otherwise the CTM is not affected; you will
- likely want to execute "initmatrix" afterwards.
-
- The interactions of this routine with the stack of saved graphics states are
- complex, leading to unexpected behaviour unless you understand exactly what
- is happening. So it is safest to think twice about calling it and always
- call it when there are no save's or gsave's active, and then to reinitialise
- the CTM immediately.
-
- This routine should not be called from within a character build, kerning,
- or imaging procedure.
-
-
- Problems, Comments, and Bugs
- ============================
-
- You will find my complete address in the header file "postlib.h". Contact
- me if you have any questions or suggestions. Don't rely on empirical
- programming.
-
- Heinz Wrobel
- <heinz@hwg.muc.de>
-
- *** EOT ***
-